//
// Created by alice on 25-4-23.
//

#ifndef MOVE_H
#define MOVE_H

#include "Tag.h"
#include "unit.h"
#include "../MapBuild/AbstractMapBuild.h"

//这个是角度检查，用于在朝向的角度值大于2倍pi、也就是一个圆周时将它的值降到2倍pi内
double RotationCheck(double & target , const double & Max = 2 * M_PI);

//这个是转向类，提供了转向方法
class Rotation {
protected:
    uint64_t id; //表示该可旋转对象的唯一标识
    uint64_t idNext=0; //用于将id递增
public:
    Rotation() {
        id = idNext++;
    }

    //重载了括号运算符，这让它可以以伪函数的形式调用，需要传入两个参数，分别是旋转目标和旋转速度
    double operator()(double & target ,const double & angular) const;
};


//表示速度所有状态的枚举
enum SpeedStatus {
    UP, //表示加速状态，也就是速度比最大值低
    MAX, //表示匀速状态，也就是速度已到达最大
    DOWN, //表示减速状态，也就是速度比最大值高
};

//当在加速状态时用来检查速度加速后是否大于最大速度的函数，会在run调用时自动调用
double SpeedCheckUP(double & target ,const double & Max);

//当在减速状态时用来检查速度加速后是否小于最大速度的函数，会在run调用时自动调用
double SpeedCheckDown(double & target , const double & Max);

//表示速度管理的类
class Velocity {
protected:

    //当单位被创建时，当单位被创建时为满速度状态
    SpeedStatus status = MAX;

    //这表示该单位当前体现出的特征，可以在该单位的类里写其他方法修改这三个数值
    double speed = 0; //表示当前的速度,当单位被创建时当前速度显然为0
    double acceleration; //表示加速度
    double speedMax; //表示速度最大值

    //这个是对速度状态的检查，会在run调用时自动调用
    void speedCheck();

public:
    Velocity(const double & acceleration , const double & speedMax) {
        this->acceleration = acceleration;
        this->speedMax = speedMax;
    }

    //这个是将速度“运行”，也就是将这次循环的初速度变为末速度
    Velocity run();

    //这个用于更改加速度，传入要更改的值
    inline void changeAcceleration(const double & acceleration);

    //这个用于更改速度最大值，传入要更改的值
    inline void changeSpeedMax(const double & speedMax);

    [[nodiscard]] inline double getAcceleration() const; //获取加速度

    [[nodiscard]] inline double getSpeedMax() const; //获取速度最大值

    [[nodiscard]] inline double getSpeed() const; //获取当前速度
};

//移动类
class Move {
public:
    //重载了括号运算符，要传三个值，分别是要移动的目标的坐标，目标朝向，移动速度
    Location operator()(Location & target ,const double & orientation ,const double & speed);
};

#endif //MOVE_H